package cn.biplam.front.template.control;

import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.front.html.HtmlDiv;
import cn.biplam.front.html.HtmlValue;
import cn.biplam.front.html.base.Html;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.html.base.Const.Float_Type;
import cn.biplam.front.html.base.Const.Length_Unit;
import cn.biplam.front.html.base.Const.Window_Event;
import cn.biplam.front.template.Template;
import cn.biplam.front.template.control.table.Table;
import cn.biplam.front.template.control.table.TableScript;
import cn.biplam.front.template.control.table.Table.Table_Cell_Type;
import cn.biplam.front.template.control.table.TableScript.Action_Type;
import cn.biplam.front.template.control.table.cell.EmptyCell;
import cn.biplam.front.template.control.table.cell.TextCell;
import cn.biplam.front.template.control.table.cell.ThCell;

/**
 * 平面布局表，根据外部设置单元格内容的单元格内容，返回表格的平面布局界面<BR>
 * 简单用法：<BR>
 * <p> new("表ID","表对应记录ID") </p>
 * <p> putTd("单元格内容","行","列","colspan")</p>
 * <p> putTh("单元格内容","行","列","colspan")</p>
 * <p> setColWidth("行","列","宽度")</p>
 * <p> setWidth("宽度")</p>
 * <p> HtmlWindow get()</p>
 * 
 * @author XiaoRuxing 2009-5-24下午05:20:39
 * @version 1.0
 */
public class FlatTable implements Template{

	private Table table;
	/** 表ID */
	private String tableID;
	/** 主键值 */
	private String keyValue;
	/** 宽度 */
	private String width=null;
	/** 高度 */
	private String height=null;
	/** 存储当前操作单元格对象 */
	private HtmlWindow currentCell;
	/** 是否绑定单元格*/
	private boolean bindCell=true;
	private int colSize=0;

	/**
	 * 创建平面数据表
	 * @param tableID 表ID
	 * @param recordId 记录主键字段值
	 * @throws ErrorMessage
	 */
	public FlatTable(String tableID,String recordId) throws ErrorMessage{
		if(TOOLS.StringIsEmpty(tableID)){
			throw new ErrorMessage("Flat Table ID is not be set!");
		}
		table=new Table(tableID);
		table.setBindViewScript(false);
		this.keyValue=recordId;
		this.tableID=tableID;
	}

	/**
	 * 指定单元格行下标和列下标插入文本单元格
	 * @param content	单元格内容
	 * @param row		行
	 * @param col		列
	 * @throws ErrorMessage
	 */
	public void putTd(String content,int row,int col) throws ErrorMessage{
		this.putTd(content, row, col,null);
	}

	/**
	 * 指定单元格行下标、列下标和单元格所占列数插入文本单元格
	 * @param content	单元格内容
	 * @param row		行
	 * @param col		列
	 * @param colspan	单元格所占列数
	 * @throws ErrorMessage
	 */
	public void putTd(String content,int row,int col,String colspan) throws ErrorMessage{
		currentCell=new TextCell(content,tableID,this.bindCell).get();
		table.put(currentCell,row,col,colspan);
	}

	/**
	 * 指定单元格行下标和列下标插入html对象到单元格
	 * @param content 要插入对象
	 * @param row  行	
	 * @param col  列
	 * @throws ErrorMessage 
	 */
	public void putTd(HtmlWindow content,int row,int col) throws ErrorMessage{
		this.putTd(content, row, col,null);
	}

	/**
	 * 指定单元格行下标、列下标和所占列数插入html对象到单元格
	 * @param content 要插入对象
	 * @param row	  行	
	 * @param col	  列	
	 * @param colspan 单元格所占列数
	 * @throws ErrorMessage 
	 */
	public void putTd(HtmlWindow content,int row,int col,String colspan) throws ErrorMessage{
		this.putTd(content, row, col, colspan, null);
	}

	/**
	 * 指定单元格行下标、列下标、所占列数和所占行数插入html对象到单元格
	 * @param content 要插入对象
	 * @param row	  行	
	 * @param col	  列	
	 * @param colspan 单元格所占列数
	 * @param rowspan 单元格所占行数 
	 * @throws ErrorMessage 
	 */
	public void putTd(HtmlWindow content,int row,int col,String colspan,String rowspan) throws ErrorMessage{
		EmptyCell cell=new EmptyCell(this.bindCell);
		cell.put(content);
		currentCell=cell.get();
		table.put(currentCell, row, col,colspan,rowspan);
	}

	/**
	 * 指定单元格行下标和列下标插入标题
	 * @param content 标题内容
	 * @param row     行
	 * @param col	  列	
	 * @throws ErrorMessage 
	 */
	public void putTh(String content,int row,int col) throws ErrorMessage{
		currentCell=new ThCell(content,this.bindCell).get();
		table.put(currentCell,row,col,Table_Cell_Type.TH);
	}

	/**
	 * 插入标题单元格到表尾
	 * @param content 标题内容
	 * @throws ErrorMessage 
	 */
	public void putTh(String content) throws ErrorMessage{
		currentCell=new ThCell(content,this.bindCell).get();
		table.put(currentCell,Table_Cell_Type.TH);
	}

	/**
	 * 指定单元格行下标、列下标和所占列数插入标题
	 * @param content  标题内容
	 * @param colspan  所占列数
	 * @param row		行下标
	 * @param col		列下标
	 * @throws ErrorMessage 
	 */
	public void putTh(String content,int row,int col,String colspan) throws ErrorMessage{
		currentCell=new ThCell(content,this.bindCell).get();
		table.put(currentCell,row,col,colspan,null,Table_Cell_Type.TH);
	}

	/**
	 * 指定单元格行下标和列下标插入html对象到标题
	 * @param content 要插入标题对象
	 * @param row  行	
	 * @param col  列
	 * @throws ErrorMessage 
	 */
	public void putTh(HtmlWindow content,int row,int col) throws ErrorMessage{
		EmptyCell cell=new EmptyCell(this.bindCell);
		cell.put(content);
		currentCell=cell.get();
		table.put(currentCell, row, col,Table_Cell_Type.TH);
	}

	/**
	 * 设置指定列的宽度(px)
	 * @param col   列下标
	 * @param value 列宽度值
	 * @throws ErrorMessage
	 */
	public void setColWidth(int col,String value) throws ErrorMessage{
		this.setColWidth(col, value, Length_Unit.px);
	}

	/**
	 * 设置列大小(以英文字符数计算,一个中文字符等于2个英文字符)<BR>
	 * 每单元格左右空白宽度各2px,单元格内边框宽度2px,每格共加6px(在字符宽度基础上)<BR>
	 * 如果单元格里是超链接,则需要保留2个字符的宽度作为超链接页面基本宽度
	 * @param col  列下标
	 * @param size 列所占字符数
	 * @throws ErrorMessage 
	 */
	public void setColSize(int col,int size) throws ErrorMessage{
		this.colSize+=size;
		int colLength=TOOLS.getPxLengthNorm(size);
		colLength=colLength+6;
		this.setColWidth(col,TOOLS.intToString(colLength));
	}

	/**
	 * 返回总的列字符宽度
	 * @return int
	 */
	public int getColSize() {
		return colSize;
	}

	/**
	 * 设置列大小(以英文字符数计算,一个中文字符等于2个英文字符)<BR>
	 * 每单元格左右空白宽度各2px,单元格内边框宽度2px,每格共加6px(在字符宽度基础上)<BR>
	 * 如果单元格里是超链接,则需要保留2个字符的宽度作为超链接页面基本宽度 
	 * @param row 行下标
	 * @param col  列下标
	 * @param size 列所占字符数
	 * @throws ErrorMessage 
	 */
	public void setColSize(int row,int col,int size) throws ErrorMessage{
		this.colSize+=size;
		int colLength=TOOLS.getPxLengthNorm(size);
		colLength=colLength+6;
		this.setColWidth(row,col,TOOLS.intToString(colLength));
	}

	/**
	 * 设置指定列宽度，宽度单位可以指定
	 * @param col   列下标   
	 * @param value 列宽度值
	 * @param unit  列宽度单位
	 * @throws ErrorMessage 
	 */
	public void setColWidth(int col,String value,Length_Unit unit) throws ErrorMessage{
		this.setColWidth(0, col, value, unit);
	}

	/**
	 * 设置指定列宽度，宽度单位可以指定
	 * @param row  行下标
	 * @param col   列下标   
	 * @param value 列宽度值
	 * @throws ErrorMessage 
	 */
	public void setColWidth(int row,int col,String value) throws ErrorMessage{
		table.setColWidth(value, row, col,Length_Unit.px);
	}

	/**
	 * 设置指定列宽度，宽度单位可以指定
	 * @param row  行下标
	 * @param col   列下标   
	 * @param value 列宽度值
	 * @param unit  列宽度单位
	 * @throws ErrorMessage 
	 */
	public void setColWidth(int row,int col,String value,Length_Unit unit) throws ErrorMessage{
		table.setColWidth(value, row, col,unit);
	}


	/**
	 * 设置表格占位宽度
	 * @param value  宽度值
	 * @throws ErrorMessage
	 */
	public void setWidth(String value) throws ErrorMessage{
		this.width=value;
	}

	/**
	 * 返回表格占位宽度 
	 * @return	String
	 */
	public String getWidth(){
		return this.width;
	}

	/**
	 * 设置表格占位高度
	 * @param value 高度值
	 * @throws ErrorMessage
	 */
	public void setHeight(String value) throws ErrorMessage{
		this.height=value;
	}

	/**
	 * 获取表格占位高度 
	 * @return 表格占位高度
	 */
	public String getHeight(){
		return this.height;
	}

	/**
	 * 绑定当前单元格对象到脚本事件
	 * @param event   触发事件
	 * @param action  表格操作类型
	 * @param actID   ActID
	 * @param targetID 目标ID
	 * @throws ErrorMessage
	 */
	public void setColAction(Window_Event event,Action_Type action,
			String actID,String targetID) throws ErrorMessage{
		currentCell.bind(event, TableScript.getBindScript(action, tableID, actID, targetID,this.keyValue));
	}

	/**
	 * 放置非行列对象的额外隐藏对象到表格
	 * @param html 
	 * @throws ErrorMessage 
	 */
	public void putExtend(Html html) throws ErrorMessage{
		this.table.putExtend(html);
	}

	/**
	 * 获取平面表界面
	 * @return 平面表界面
	 * @throws ErrorMessage
	 */
	public HtmlWindow get() throws ErrorMessage {
		/** 插入table的主键值 */
		table.putExtend(new HtmlValue(tableID+"r",null,keyValue));
		if(width!=null){
			table.setWidth(width);
			table.setClientWidth(width);
		}else{
			table.setWidth("100", Length_Unit.percent);
			table.setClientWidth("100", Length_Unit.percent);
		}
		if(this.height!=null){
			table.setHeight(this.height);
		}
		HtmlWindow tb = table.get();
		if(this.bindCell)
			tb.bind("tdBind('"+tb.getID()+"');");
		return tb;
	}

	/**
	 * 设置是否绑定单元格(在放入单元格之前设置)
	 * @param bindCell
	 */
	public void setBindCell(boolean bindCell) {
		this.bindCell = bindCell;
	}
	
	/**
	 * 依据行数量计算高度
	 * @param rows				行数量
	 * @param titleHaveButton	标题行内是否有按钮
	 * @param rowHaveButton		数据行内是否有按钮
	 * @return	int
	 */
	public static int GetHeight(int rows,boolean titleHaveButton,boolean rowHaveButton){
		return (titleHaveButton?28:23)+(rowHaveButton?25:24)*rows;
	}

	/**
	 * 返回全部是标题行的高度
	 * @param rows	行数
	 * @return int
	 */
	public static int GetTitleHeight(int rows){
		return 23*rows;
	}

	/**
	 * 计算宽度
	 * @param totalChars	总字符数量
	 * @param cols			总列数量
	 * @return int
	 */
	public static int GetWidth(int totalChars,int cols){
		return TOOLS.getPxLengthNorm(totalChars)+6*cols;
	}
	
	/**
	 * 返回文本单元格内容的有效宽度(HtmlText/Text)<BR>
	 * @param colWidth	表格设置的列宽度
	 * @return	int
	 */
	public static int GetInnerTextWidth(int colWidth){
		//dt.padding左右各3 st.margin左右各2,dt的边框2 合计:3*2+2*2+2=12
		return colWidth-12;
	}
	
	/**
	 * 返回单元格非文本Div的有效宽度(Anchor,HtmlDiv)
	 * @param colWidth	表格设置的列宽度
	 * @return	int
	 */
	public static int GetInnerDivWidth(int colWidth){
		//扣除st.margin的左右边距4像素
		return colWidth-8;
	}
	
	/**
	 * 依据文本有效宽度，返回单元格内文本可用的字符数
	 * @param innerWidth	文本有效宽度 GetInnerTextWidth
	 * @return	int
	 */
	public static int GetInnerChars(int innerWidth){
		//超链接留白宽度10像素
		return GetInnerTextWidth(innerWidth)/6;
	}

	/**
	 * 返回表格最后一个动态宽度单元格的可用宽度
	 * @param totalWidth	表格总宽度(px)
	 * @param otherWidth	其它单元格总的宽度(px)
	 * @param cols			表格列数
	 * @return int
	 */
	public static int GetLessWidth(int totalWidth,int otherWidth,int cols){
		/**每增加一列减去1像素的边框宽度*/
		return totalWidth-otherWidth-cols-1;
	}
	
	/**
	 * 返回包含内容的居中对齐的Div
	 * @param content	内容页面对象
	 * @param width		单元格页面宽度
	 * @param bindCell	是否绑定单元格
	 * @return	HtmlWindow
	 * @throws ErrorMessage
	 */
	public static HtmlWindow GetCenterDiv(HtmlWindow content, int width,boolean bindCell) throws ErrorMessage{
		HtmlWindow div ;
		int btWidth=content.getLength();
		int lessWidth=width-btWidth-6;//单元格左右留白各3
		if(bindCell)//绑定单元格情况下，减去绑定的边框宽度2
			lessWidth-=2;
		if(lessWidth>1){
			div= new HtmlDiv();
			HtmlWindow s=new HtmlDiv();
			s.setStyleWidth(lessWidth/2);
			s.setFloat(Float_Type.Left);
			content.setFloat(Float_Type.Left);
			div.put(s);
			div.put(content);
		}else{
			div=content;
		}
		return div;
	}

}
